package com.xqboss.apps.service.order.pay.impl;

import com.xqboss.apps.domain.order.PayApply;
import com.xqboss.apps.domain.user.SysUserWallet;
import com.xqboss.apps.dto.order.SignPayDto;
import com.xqboss.apps.dto.order.TradeResultDto;
import com.xqboss.apps.dto.order.WalletPayDto;
import com.xqboss.apps.enums.order.PayStatusEnum;
import com.xqboss.apps.enums.user.PayTypeEnum;
import com.xqboss.apps.enums.user.UserWalletEnum;
import com.xqboss.apps.enums.user.WalletChangeTypeEnum;
import com.xqboss.apps.service.order.PayApplyService;
import com.xqboss.apps.service.order.pay.PayExecutor;
import com.xqboss.apps.service.user.SysUserWalletService;
import com.xqboss.common.constant.HttpStatus;
import com.xqboss.common.core.domain.model.LoginUser;
import com.xqboss.common.exception.ServiceException;
import com.xqboss.common.utils.SecurityUtils;
import com.xqboss.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Objects;

/**
 * @author Trent
 * @date 2023/8/23
 */
@Component(value = PayTypeEnum.Code.Wallet)
public class WalletPayExecutor extends PayExecutor {

    @Autowired
    private SysUserWalletService userWalletService;
    @Autowired
    private PayApplyService payApplyService;
    @Autowired
    private ISysUserService userService;

    @Override
    public SignPayDto signPay(PayApply info) {
        // 检测钱包余额是否满足
        SysUserWallet wallet = userWalletService.getWallet(info.getUserId(), UserWalletEnum.CASH);
        if (wallet.getAmount().compareTo(info.getOrderAmount()) < 0) {
            throw new ServiceException("余额不足！", HttpStatus.Insufficient_Balance);
        }
        SignPayDto dto = new SignPayDto();
        dto.setPayInfo(null);
        dto.setOutTradeNo(String.valueOf(info.getId()));
        return dto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TradeResultDto verifyCallback(HttpServletRequest request, Object params) {
        WalletPayDto dto;
        if (params instanceof WalletPayDto) {
            dto = (WalletPayDto) params;
        } else {
            throw new ServiceException("参数错误！");
        }
        // 获取支付单号信息
        PayApply payApply = payApplyService.getById(dto.getTradeId());
        // 获取用户信息
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (dto.getIsCheckPwd()){
            // 1. 校验钱包密码
            userService.checkPayPwd(loginUser.getUserId(), dto.getPayPwd());
        }
        if (Objects.isNull(payApply)) {
            throw new ServiceException("支付信息不存在！");
        }
        if (!Objects.equals(payApply.getOrderMainId(), dto.getOrderId())
                || payApply.getOrderAmount().compareTo(dto.getPrice()) != 0) {
            throw new ServiceException("支付信息变更！");
        }
        if (!Objects.equals(payApply.getUserId(), loginUser.getUserId())) {
            throw new ServiceException("仅能支付自己的订单！");
        }
        if (payApply.getPayStatus() != PayStatusEnum.WAIT_PAY) {
            if (payApply.getPayStatus() == PayStatusEnum.TRADE_SUCCESS) {
                throw new ServiceException("请勿重复支付！");
            }
            throw new ServiceException("支付失败！");
        }
        if (LocalDateTime.now().isAfter(payApply.getExpireTime())) {
            throw new ServiceException("订单已超时！");
        }

        // 2. 扣除用户钱包余额
        if(payApply.getOrderAmount().compareTo(BigDecimal.ZERO) > 0){
            userWalletService.reduce(loginUser.getUserId(), UserWalletEnum.CASH, payApply.getOrderAmount(), WalletChangeTypeEnum.ORDER_PAY, payApply.getOrderMainId(), "订单支付");
        }
        TradeResultDto result = new TradeResultDto();
        result.setPayTime(LocalDateTime.now());
        result.setPayAmount(payApply.getOrderAmount());
        result.setTradeNo(String.valueOf(payApply.getId()));
        result.setOutTradeNo(String.valueOf(payApply.getId()));
        result.setTotalAmount(payApply.getOrderAmount());
        result.setReceiptAmount(payApply.getOrderAmount());
        result.setBuyerId(String.valueOf(loginUser.getUserId()));
        result.setBuyerAccount(loginUser.getUsername());
        return result;
    }

    @Override
    public TradeResultDto queryTrade(PayApply info) {
        throw new ServiceException("订单未支付！");
    }

    @Override
    public boolean cancelPay(PayApply payApply) {
        return true;
    }

}
